package com.huangxt.test.excel;


import java.math.BigDecimal;

/**
 * 计算工具类
 */
public class CalculationFormulaUtil {
    public static final BigDecimal HUNDRED = new BigDecimal(100);

    public static BigDecimal backcalculation(String rate_caliber,BigDecimal signAmt,BigDecimal rate1,BigDecimal apply_tnr,BigDecimal target,BigDecimal diff,BigDecimal f,BigDecimal t){
        int num = 0;
        BigDecimal z =f;
        do {
            if (rateCaliberCalculation(rate_caliber,signAmt,rate1,apply_tnr,f).subtract(target).abs().compareTo(diff)<=0){
                return f;
            }
            if (rateCaliberCalculation(rate_caliber,signAmt,rate1,apply_tnr,t).subtract(target).abs().compareTo(diff)<=0){
                return t;
            }
            z=f.add(t).divide(new BigDecimal(2));
            if(rateCaliberCalculation(rate_caliber,signAmt,rate1,apply_tnr,z).compareTo(target)
                    *(rateCaliberCalculation(rate_caliber,signAmt,rate1,apply_tnr,t).compareTo(target))<0){
                f = z;
            }else if(rateCaliberCalculation(rate_caliber,signAmt,rate1,apply_tnr,z).compareTo(target)
                    *(rateCaliberCalculation(rate_caliber,signAmt,rate1,apply_tnr,f).compareTo(target))<0){
                t = z;
            }else if(rateCaliberCalculation(rate_caliber,signAmt,rate1,apply_tnr,z).compareTo(target)==0){
                return z;
            }else{
                return null;
            }
            num++;
        }while (num<10000);
        return null;
    }
    /**
     * 费率口径
     * @param rate_caliber 统计模式
     * @param signAmt 签约金额
     * @param rate1 利率 6% 送6
     * @param apply_tnr 期限
     * @param costZG 最高成本 15.4%送15.4
     * @return 可执行最高费率1% 返回1
     */
    public static BigDecimal rateCaliberCalculation(String rate_caliber,BigDecimal signAmt,BigDecimal rate1,BigDecimal apply_tnr,BigDecimal costZG){
        if("IRR".equalsIgnoreCase(rate_caliber)){
            return rateIrrCalculation(signAmt,rate1.divide(HUNDRED),apply_tnr,costZG.divide(HUNDRED));
        }else if("APR".equalsIgnoreCase(rate_caliber)){
            return rateAprCalculation(signAmt,rate1.divide(HUNDRED),apply_tnr,costZG.divide(HUNDRED));
        }
        return null;
    }

    /**
     * IRR口径
     * @param signAmt 签约金额
     * @param rate1 利率
     * @param apply_tnr 期限
     * @param costZG 最高成本
     * @return 可执行最高费率
     */
    public static BigDecimal rateIrrCalculation(BigDecimal signAmt,BigDecimal rate1,BigDecimal apply_tnr,BigDecimal costZG){
        BigDecimal fz = signAmt.multiply(rate1).multiply((rate1.add(new BigDecimal("12")))
                .pow(Integer.parseInt(apply_tnr.toString())));
        BigDecimal fm = (rate1.add(new BigDecimal("12"))).pow(Integer.parseInt(apply_tnr.toString()))
                .add(new BigDecimal("12").pow(Integer.parseInt(apply_tnr.toString())).multiply(new BigDecimal(-1)))
                .multiply(new BigDecimal(12));
        BigDecimal rateBank = fz.divide(fm, 2, BigDecimal.ROUND_HALF_UP);//银行本息每月还款金额

        //最高成本下等额每月还款金额 = 〔贷款本金×最高成本下月利率×（1＋最高成本下月利率）＾期数〕÷〔（1＋最高成本下月利率）＾期数－1〕÷ 还款月数
        BigDecimal fzZH = signAmt.multiply(costZG).multiply((costZG.add(new BigDecimal("12")))
                .pow(Integer.parseInt(apply_tnr.toString())));
        BigDecimal fmZH = (costZG.add(new BigDecimal("12"))).pow(Integer.parseInt(apply_tnr.toString()))
                .add(new BigDecimal("12").pow(Integer.parseInt(apply_tnr.toString())).multiply(new BigDecimal(-1)))
                .multiply(new BigDecimal(12));
        BigDecimal rateZH = fzZH.divide(fmZH, 2, BigDecimal.ROUND_HALF_UP);//最高成本下每月还款金额
        BigDecimal signRate = (rateZH.subtract(rateBank)).multiply(new BigDecimal("100")).divide(signAmt, 2, BigDecimal.ROUND_DOWN);//月保费本金比例
        return signRate;
    }

    /**
     * APR口径
     * @param signAmt 签约金额
     * @param rate1 利率
     * @param apply_tnr 期限
     * @param costZG 最高成本
     * @return 可执行最高费率
     */
    public static BigDecimal rateAprCalculation(BigDecimal signAmt,BigDecimal rate1,BigDecimal apply_tnr,BigDecimal costZG){
        //等额本息总和 = [贷款本金×月利率×（1+月利率）^还款月数]÷[（1+月利率）^还款月数－1]*期数
        BigDecimal fz = signAmt.multiply(rate1).multiply((rate1.add(new BigDecimal("12")))
                .pow(Integer.parseInt(apply_tnr.toString())));
        BigDecimal fm = (rate1.add(new BigDecimal("12"))).pow(Integer.parseInt(apply_tnr.toString()))
                .add(new BigDecimal("12").pow(Integer.parseInt(apply_tnr.toString())).multiply(new BigDecimal(-1)))
                .multiply(new BigDecimal(12));
        BigDecimal amount = fz.multiply(apply_tnr).divide(fm, 2, BigDecimal.ROUND_HALF_UP);//等额本息还款方式下的本息和
        BigDecimal amountBank = amount.subtract(signAmt);//银行利息总和
        BigDecimal costBank = amountBank.multiply(new BigDecimal("12"))
                .divide((signAmt.multiply(apply_tnr)), 4, BigDecimal.ROUND_UP);//银行利息成本
        BigDecimal signRate = (costZG.subtract(costBank)).multiply(new BigDecimal("100"))
                .divide(new BigDecimal("12"), 2, BigDecimal.ROUND_DOWN);//月保费本金比例
        return signRate;
    }
}

